Scope of Variables
This lesson gives details on scope of a variable and the difference between value and reference types.
We'll cover the following
Scope of a variable#
A variable of any type is only known in a certain range of a program, called its scope. In a programming language, there are two main types of scopes:
- Global scope
- Local scope
Global scope#
The scope of the variables declared outside of any function (in other words at the top level) is called global scope. Global scope is also known as package scope because the variables with such scope are visible and available in all source files of a package.
Local scope#
The scope of the variables declared inside a function is called local scope. They are only known in that function; the same goes for parameters and return variables of a function.
In simple words, mostly, you can think of a scope as the code block ( surrounded by { } ) in which the variable is declared. Run the following program to visualize the concept of scope.
Let’s first discuss the number variable. It’s declared outside any function. So it has a global scope. It can be accessed and changed anywhere inside a code. We declare and initialize number with value 5 at line 4. At line 8, the value is printed, and we see 5 as an output. Then in the next line, we reassign: number=10, it changes the value of number to 10. Now when we print its value on line 10 answer is 10.
Although identifiers have to be unique, an identifier declared in a block may be redeclared in an inner block, but then the redeclared variable takes priority and shadows the outer variable with the same name; if used, care must be taken to avoid subtle errors.
Printing#
We have been using the Println function from the fmt package so far, to print output to console. This package provides us another function, Printf, that prints the output on console but has a different format. It generally uses a format-string as its first argument:
func Printf(format string, list of variables to be printed)
This format string can contain one or more format-specifiers. Some common format specifiers are:
- %d specifies format for integral values.
- %s specifies format for string values.
- %v specifies the general default format.
How about modifying the above code by using Printf now?
As you can see at line 8 and line 10, we use format specifier %d because number is an integer, where \n means to print a newline at the end. At line 11, we use %t, as a format specifier for booleans.
Value types and reference types#
Memory in a computer is used in programs as an enormous number of boxes (that’s how we will draw them), called words. All words have the same length of 32 bits (4 bytes) or 64 bits (8 bytes), according to the processor and the operating system, and are identified by their memory address (represented as a hexadecimal number). All variables of elementary (primitive) types like int, float, bool, string, etc., are value types, which means they point directly to their value contained in memory as:
When assigning with =, the value of a value type assigns to another variable. For example, if we do j = i, a copy of the original value i is made in memory:
The address of the word where a variable is stored is its memory address. Variables of value type are contained in a stack memory.
The actual value of the address will differ from machine to machine and even on different executions of the same program as each machine could have a different memory layout and also the location where it is allocated could be different.
More complex data which needs several words are usually treated as reference types. Look at the figure below:
A reference type variable r1 contains the address of the memory location where the value of r1 is stored (or at least the 1st word of it). This address which is called a pointer is also contained in a word. The different words a reference type points to could be sequential memory addresses (the memory layout is said to be contiguous), which is the most efficient storage for computation; or the words could be spread around, each pointing to the next. To assign a reference type only address is copied:
When assigning r2 = r1, only the reference (the address) is copied. If the value of r1 is modified, all references of that value (like r1 and r2) then point to the modified content. The values that are referenced are usually stored in the heap, which is garbage collected and which is much larger memory space than a stack.
Now that you have a complete insight into variables in Go, let’s see data types in detail.
Variables
Elementary Types